package com.example.administrator.exkotlin.base.lambda

/**
 * Lambda的实例
 * */
object LambdaEx {
    private val list = listOf<String>("Dog", "Cat", "Fesh", "Tiger")
    //没有Lambda
    fun ExLamda_1() {
        var max = ""
        for (s in list) {
            if (s.length > max.length) {
                max = s
            }
        }
        println(max)
    }

    /**
     * 简化版本的lambda表达式
     * 接下来ExLambda_3，ExLambda_4展示表达式的简化过程
     * */
    fun ExLambda_2() {
        val max = list.maxBy { it.length }
        println(max)
    }

    /**
     *完整版本
     * {参数名：参数类型，参数名：参数类型.....->函数体，不宜过长}
     * 最后一行作为返回值
     * */
    fun ExLambda_3() {
        var lambda = { animal: String -> animal.length }
        val max = list.maxBy(lambda)
        val max1 = list.maxBy { it.length }
        println(max)
    }

    /**
     *
     *1.lambda表达式不用单独用参数接收
     *    list.maxBy ({animal:String ->animal.length})
     * 2.当Lambda参数是函数最后一个参数时，可以将表达式，移到外面
     * list.maxBy (){animal:String ->animal.length}
     * 3.当Lambda参数是函数唯一一个参数的时候，可以将函数的括号去掉
     * list.maxBy {animal:String ->animal.length}
     * 4.利用推倒机制，Lambda参数大多情况不必申明参数类型
     * list.maxBy {animal ->animal.length}
     * 5.当Lambda参数列表中只有一个参数的时候，也不必申明参数名字，直接用it 关键字来代替即可
     * list.maxBy {it.length}
     *
     * */
    fun Exlambda_4() {
//        list.maxBy ({animal:String ->animal.length})
//        list.maxBy (){animal:String ->animal.length}
//        list.maxBy {animal:String ->animal.length}
//        list.maxBy {animal ->animal.length}
        val max = list.maxBy { it.length }
        println(max)

    }

    /**
     * 使用map函数，将list集合中所有的元素都变成大写
     * */
    fun ExLambda_map() {
        val list1 = list.map { it.toUpperCase() }
        for (b in list1) {
            println(b)
        }
    }

    /***
     * 使用fliter函数过滤条件生成新的集合
     *
     * */
    fun Exlambda_filter() {
        val list1 = list.filter { it.length > 3 }
        for (s in list1) {
            println(s)
        }
    }

    /**
     * 同时使用filter和map
     * */
    fun Exlambda_fliterAndMap() {
        //先过滤，后映射
        for (s in list.filter { it.length > 3 }.map { it.toUpperCase() }) {
            println(s)
        }

        //先映射，后过滤，效率低，因为进行了没比要的映射操作
        for (s in list.map { it.toUpperCase() }.filter { it.length > 3 }) {
            println(s)
        }
    }

    /**
     * any函数判断集合中是否有至少一个满足条件
     * */
    fun Exlambda_any() = list.any { it.length > 3 }

    /**
     * all函数判断集合中是否全部满足条件
     * */
    fun Exlambda_all() = list.all { it.length > 3 }


    /**
     * lambda
     * 使用函数式API来调用java方法
     * java方法满足：接收一个java单抽象方法接口参数（接口只有一个待实现方法）
     *
     * */
    fun Exlambda_java_Thread_1() {
        Thread(object : Runnable {
            override fun run() {
                println("this is a new thread" + Thread().name)
            }

        }).start()

        val myThread: Runnable = MyRunnable()
        Thread(myThread).start()
        Thread(MyRunnable()).start()
    }

    class MyRunnable : Runnable {
        override fun run() {
            println("this is my Runnable" + Thread().name)
        }

    }

    /**
     * 简化：
     * 1.匿名类，接口匿名类的实现由于没有new关键字，所以用是object关键字代替
     * 2.因为Runnable只有一个实现run方法，所以不run也可以
     *   Thread(Runnable { println("this is a new thread"+Thread().name) }).start()
     * 3.因为Thread参数列表只有一个单抽象Runnable接口参数，所以也可以省略Runnable
     *   Thread( { println("this is a new thread" + Thread().name) }).start()
     * 4.因为当lambda表达式是方法最后一个参数，且只有一个参数时候，可以将括号一道外面，并省略（）
     *   Thread{ println("this is a new thread" + Thread().name) }.start()
     * */
    fun Exlambda_java_Thrad_2() {
        Thread(Runnable { println("this is a new thread" + Thread().name) }).start()
        Thread({ println("this is a new thread" + Thread().name) }).start()
        Thread { println("this is a new thread" + Thread().name) }.start()

    }


}